/**
 * 最佳实践
 *   需要只读字符串时，尤其是函数参数时更喜欢std::string_view使用
 * 
 * std::string为了解决初始化（或复制）成本高昂的问题，引入了 C++17 std::string_view（位于 <string_view> 头文件中）。
 * 提供对现有字符串（C 样式字符串、 a或另一个）std::string_view的只读访问，而无需进行复制。
 * 
 * 常量表达式std::string_view
 *   与 , 不同的是std::string，std::string_view完全支持 constexpr
 * 
 * constexpr std::string_view当需要字符串符号常量时，这是首选
 * 
 * 
 * 
 * 
 * 视图取决于被查看的对象。如果在视图仍在使用时正在查看的对象被修改或销毁，则会导致意外或未定义的行为。
 * 
 * 最佳用途std::string_view是作为只读函数参数。这允许我们传入 C 风格的字符串、std::string或std::string_view参数，而无需进行复制，因为这std::string_view将创建参数的视图。
 * 
 * 因为std::string_view它是一个视图，它包含让我们通过“关闭窗帘”来修改视图的函数。这不会以任何方式修改正在查看的字符串，只是修改视图本身。
 *   成员remove_prefix()函数从视图左侧删除字符。
 *   成员remove_suffix()函数从视图右侧删除字符。
 * 
 * 
 * C 风格的字符串文字和 std::string 始终以 null 终止。
 * std::string_view 可以是也可以不是 null 终止的。
 * 
 * 如果您有一个非空终止的字符串std::string_view，并且由于某种原因需要一个空终止的字符串，请将 转换std::string_view为std::string.
 * 
 */


#include <iostream>
#include <string>
#include <string_view>

void printSV(std::string_view str)
{
    std::cout << str << '\n';
}

std::string getName()
{
    std::string s { "Alex" };
    return s;
}

int main()
{
    printSV("Hello, world!"); // call with C-style string literal

    std::string s2{ "Hello, world!" };
    printSV(s2); // call with std::string

    std::string_view s3 { s2 };
    printSV(s3); // call with std::string_view


    using namespace std::string_literals;      // access the s suffix
    using namespace std::string_view_literals; // access the sv suffix

    std::cout << "foo\n";   // no suffix is a C-style string literal
    std::cout << "goo\n"s;  // s suffix is a std::string literal
    std::cout << "moo\n"sv; // sv suffix is a std::string_view literal


    constexpr std::string_view s{ "Hello, world!" }; // s is a string symbolic constant
    std::cout << s << '\n'; // s will be replaced with "Hello, world!" at compile-time


    // 使用不当std::string_view
    std::string_view sv{};

    { // create a nested block
        std::string s{ "Hello, world!!!" }; // create a std::string local to this nested block
        sv = s; // sv is now viewing s
    } // s is destroyed here, so sv is now viewing an invalid string

    std::cout << sv << '\n'; // undefined behavior


    std::string_view name { getName() }; // name initialized with return value of function
    std::cout << name << '\n'; // undefined behavior


    std::string sss { "Hello, world!" };
    std::string_view svvv { sss }; // sv is now viewing s

    sss = "Hello, universe!";    // modifies s, which invalidates sv (s is still valid)
    std::cout << svvv << '\n';   // undefined behavior


    std::string_view str{ "Peach" };
	std::cout << str << '\n';

	// Remove 1 character from the left side of the view
	str.remove_prefix(1);
	std::cout << str << '\n';

	// Remove 2 characters from the right side of the view
	str.remove_suffix(2);
	std::cout << str << '\n';

	str = "Peach"; // reset the view
	std::cout << str << '\n';


    return 0;
}